package MAINWIN;

//Komissarov D.

//method to obtain program listing
//Vector<String[]> CCPUBlackBox.getCurrentProgram().outputProgramListingToFrame()
//returns vector of string sets String[]
//where String[] is:
//String[0] command index(ordinal) number
//String[1] pointer on current command ("*" if it points on this command, "" if not)
//String[2] command ID : two Hex numbers (e.g. 0xFF), "null" if no command was specified
//String[3] command button (e.g. [F] + [sin] or [+])
//String[4] command text explanation

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.GridLayout;
import java.awt.BorderLayout;

import CalculationCore.CProgramListing;
import Resources.CEnvironment;
import java.util.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;

public class CPMode extends JFrame {


	private static final long serialVersionUID = 1797117227699344315L;
	CProgramListing currentProgram;
	ArrayList<MyBean> beans = new ArrayList<MyBean>();
	TableModel model = new MyTableModel(beans);
	JTable table = new JTable(model);

	CPMode(String title, final CProgramListing currentProgram) {

		setSize(598, 400);
		setLocationRelativeTo(null);
		setMinimumSize(new Dimension(500, 400));
		//setResizable(isMinimumSizeSet());
		setTitle(title);

		this.currentProgram = currentProgram;
		tableUpdate();

		// Table panel
		GridLayout gLayout = new GridLayout(1, 1, 5, 5);
		JPanel panel = new JPanel();
		panel.setLayout(gLayout);
		panel.setBorder(new EmptyBorder(30, 20, 20, 20));
		getContentPane().add(panel, BorderLayout.CENTER);
		panel.add(new JScrollPane(table));

		// buttons panel
		GridLayout gLayout_1 = new GridLayout(10, 1, 5, 5);
		JPanel panel_1 = new JPanel();
		panel_1.setLayout(gLayout_1);
		panel_1.setBorder(new EmptyBorder(30, 0, 20, 20));
		getContentPane().add(panel_1, BorderLayout.EAST);

		JButton btnSave = new JButton(CEnvironment.pModeSave);
		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				programSave();
			}
		});
		btnSave.setSize(new Dimension(50, 20));
		panel_1.add(btnSave);

		JButton btnLoad = new JButton(CEnvironment.pModeLoad);
		btnLoad.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				programLoad();
			}
		});
		btnSave.setSize(new Dimension(50, 20));
		panel_1.add(btnLoad);

		// Set table column size
		table.getColumnModel().getColumn(0).setMinWidth(40);
		table.getColumnModel().getColumn(0).setMaxWidth(40);
		table.getColumnModel().getColumn(0).setPreferredWidth(40);
		table.getColumnModel().getColumn(1).setMinWidth(30);
		table.getColumnModel().getColumn(1).setMaxWidth(30);
		table.getColumnModel().getColumn(1).setPreferredWidth(30);
		table.getColumnModel().getColumn(2).setMinWidth(50);
		table.getColumnModel().getColumn(2).setMaxWidth(50);
		table.getColumnModel().getColumn(2).setPreferredWidth(50);
		table.getColumnModel().getColumn(3).setMinWidth(100);
		table.getColumnModel().getColumn(3).setMaxWidth(100);
		table.getColumnModel().getColumn(3).setPreferredWidth(100);
	}

	public void programLoad() {

		FileDialog fDialog = new FileDialog(this, CEnvironment.fileLoadTitle,
				FileDialog.LOAD);
		fDialog.setFile(CEnvironment.fileType);
		fDialog.setDirectory(".\\");

		fDialog.setVisible(true);
		if (fDialog.getFile() != null) {
			try {
				// Open the file that is the first
				// command line parameter
				FileInputStream fstream = new FileInputStream(
						fDialog.getDirectory() + fDialog.getFile());
				// Get the object of DataInputStream
				DataInputStream in = new DataInputStream(fstream);
				BufferedReader br = new BufferedReader(
						new InputStreamReader(in));
				String strLine;
				// Read File Line By Line
				while ((strLine = br.readLine()) != null) {
					currentProgram.inputProgramListingFromTXTFile(strLine);
				}
				// Close the input stream
				in.close();

			} catch (Exception e) {// Catch exception if any
				System.err.println("Read file error: " + e.getMessage());
			}
			tableUpdate();
		}
	}

	public void programSave() {

		FileDialog fDialog = new FileDialog(this, CEnvironment.fileSaveTitle,
				FileDialog.SAVE);
		fDialog.setFile(CEnvironment.fileType);
		fDialog.setDirectory(".\\");

		fDialog.setVisible(true);
		if (fDialog.getFile() != null) {
			try {
				// Create file
				FileWriter fstream = new FileWriter(fDialog.getDirectory()
						+ fDialog.getFile());
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(currentProgram.outputProgramListingToTXTFile());
				// Close the output stream
				out.close();
			} catch (Exception e) {
				// Catch exception if any
				System.err.println("Save file error: " + e.getMessage());
			}
		}
	}
	
	synchronized public void tableUpdate() {

		try{
			Vector<String[]> res = currentProgram.outputProgramListingToFrame();
			String[] strStruct;

			beans.clear();
			for (int index = 0; index < res.size(); index++) {
				strStruct = res.get(index);
				beans.add(new MyBean(strStruct[0], strStruct[1], strStruct[2],
						strStruct[3], strStruct[4]));

			}
			table.revalidate();
			table.repaint();
		} catch( Exception ex ) {
			System.out.println(" !!! Error during table update \n" + ex.getMessage());
		}
	}

	public class MyTableModel implements TableModel {

		private Set<TableModelListener> listeners = new HashSet<TableModelListener>();

		private List<MyBean> beans;

		public MyTableModel(List<MyBean> beans) {
			this.beans = beans;
		}

		public void addTableModelListener(TableModelListener listener) {
			listeners.add(listener);
		}

		public Class<?> getColumnClass(int columnIndex) {
			return String.class;
		}

		public int getColumnCount() {
			return 5;
		}

		public String getColumnName(int columnIndex) {
			switch (columnIndex) {
			case 0:
				return CEnvironment.pModeT0;
			case 1:
				return CEnvironment.pModeT1;
			case 2:
				return CEnvironment.pModeT2;
			case 3:
				return CEnvironment.pModeT3;
			case 4:
				return CEnvironment.pModeT4;
			}
			return "";
		}

		synchronized public int getRowCount() {
			return beans.size();
		}

		synchronized public Object getValueAt(int rowIndex, int columnIndex) {
			MyBean bean = beans.get(rowIndex);
			switch (columnIndex) {
			case 0:
				return bean.getCount();
			case 1:
				return bean.getPointer();
			case 2:
				return bean.getAddress();
			case 3:
				return bean.getButton();
			case 4:
				return bean.getDescription();
			}
			return "";
		}

		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return false;
		}

		public void removeTableModelListener(TableModelListener listener) {
			listeners.remove(listener);
		}

		public void setValueAt(Object value, int rowIndex, int columnIndex) {

		}

	}

	public class MyBean {

		private String count;
		private String pointer;
		private String address;
		private String button;
		private String description;

		public MyBean(String count, String pointer, String address,
				String button, String description) {
			this.setCount(count);
			this.setPointer(pointer);
			this.setAddress(address);
			this.setButton(button);
			this.setDescription(description);
		}

		public void setCount(String c) {
			this.count = c;
		}

		public String getCount() {
			return count;
		}

		public void setPointer(String p) {
			this.pointer = p;
		}

		public String getPointer() {
			return pointer;
		}

		public void setAddress(String a) {
			this.address = a;
		}

		public String getAddress() {
			return address;
		}

		public void setButton(String b) {
			this.button = b;
		}

		public String getButton() {
			return button;
		}

		public void setDescription(String d) {
			this.description = d;
		}

		public String getDescription() {
			return description;
		}
	}

}